import {
  CanActivate,
  ExecutionContext,
  Injectable,
  Logger,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { UserIdentity } from '@/common/auth/dto/user-identity.dto';
import { UserRole } from '@/enum';
import { UserNotFoundException } from '@/exceptions';
import { ConfigService } from '@/common/config/config.service';

@Injectable()
export class RolesGuard implements CanActivate {
  constructor(
    private readonly reflector: Reflector,
    private readonly config: ConfigService,
  ) {}

  canActivate(context: ExecutionContext): boolean {
    if (!this.config.isAuthEnabled) {
      Logger.warn(
        `Authorization has been disabled due to environment setting.
      DO NOT TURN OFF AUTHORIZATION IN PRODUCTION UNLESS YOU KNOW EXACTLY WHAT YOU'RE DOING!`,
        'RolesGuard',
      );
      return true;
    }
    const roles = this.reflector.get<UserRole[]>('roles', context.getHandler());
    if (!roles) {
      return true;
    }
    const request = context.switchToHttp().getRequest();
    const user = request.user as UserIdentity;
    if (!user) {
      throw new UserNotFoundException(
        'Authorized user is required by RolesGuard.',
      );
    }
    const hasRole = () => user.roles.some(role => roles.includes(role));
    return user.roles && hasRole();
  }
}
